﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using SsrsRenderStudio.Shared;
using SsrsRenderStudio.Configuration;
using SsrsRenderStudio.Renderer.Output.Version2013;
using SsrsRenderStudio.KnownTypesAndModels;

namespace SsrsRenderStudio.Wcf.Services
{
    public static class ReportCache
    {
        private static System.Timers.Timer _cacheTimer = new System.Timers.Timer();
        private static TimeSpan _cacheTimeToLive = new TimeSpan(0, 30, 0);

        private static bool _timerSet = false;
        private static void SetTimer(bool force = false)
        {
            if (!_timerSet || force)
            {
                _timerSet = true;

                RenderStudioServerConfig10 si = ConfigurationManager.ServerInfoFromFriendlyName10(ConfigurationManager.ApplicationConfigFromConfigPointer.ApplicationName);

                if (si != null)
                    _cacheTimeToLive = si.ReportCacheTtl;
            }

            if (!_cacheTimer.Enabled)
            {
                _cacheTimer.Interval = 60000;
                _cacheTimer.Elapsed += new System.Timers.ElapsedEventHandler(_cacheTimer_Elapsed);
                _cacheTimer.AutoReset = true;
                _cacheTimer.Start();
            }
        }

        static void _cacheTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            CleanCache();
        }

        private static Dictionary<Guid, CachedReport> _cache = new Dictionary<Guid, CachedReport>();

        public static Guid Add(Output outputDefinition)
        {
            SetTimer();

            Guid id = Guid.NewGuid();
            _cache.Add(id, new CachedReport(outputDefinition));
            Logger.Log("70005", outputDefinition.GetType().FullName, id.ToString());
            return id;
        }

        public static Output Retrieve(Guid id)
        {
            if (_cache.ContainsKey(id))
                return _cache[id].OutputDefinition;
            else
                return new NullOutput();
        }

        public static DateTime WhenWillReportExpire(Guid id)
        {
            if (_cache.ContainsKey(id))
            {
                return _cache[id].ProcessedTime + _cacheTimeToLive;
            }
            else
            {
                return DateTime.MinValue;
            }
        }

        /// <summary>
        /// Remove everything from cache.
        /// </summary>
        public static void PurgeCache()
        {
            _cache.Clear();
            _cache = new Dictionary<Guid, CachedReport>();
        }

        /// <summary>
        /// Remove stale reports from cache.
        /// </summary>
        public static void CleanCache()
        {
            Logger.Log("70006");

            List<Guid> expiredReports = new List<Guid>();

            foreach (var r in _cache)
            {
                if (DateTime.Now - r.Value.ProcessedTime > _cacheTimeToLive)
                {
                    expiredReports.Add(r.Key);
                }
            }

            foreach (var g in expiredReports)
            {
                Logger.Log("70007", g.ToString());
                _cache.Remove(g);
            }
        }
    }



    public class CachedReport
    {
        public Output OutputDefinition = null;
        public DateTime ProcessedTime = DateTime.MinValue;

        public CachedReport(Output outputDefinition)
        {
            OutputDefinition = outputDefinition;
            ProcessedTime = DateTime.Now;
        }
    }

    /*
    public class CachedReport
    {
        public EnumOutputType OutputType;
        public byte[][] RenderedBuffer;
        public string Destination;
        public string Extension;
        public string EncodingType;
        public DateTime ProcessedTime;

        public CachedReport(EnumOutputType ot, byte[][] buffer, string dest, string ext, string enc)
        {
            OutputType = ot;
            RenderedBuffer = buffer;
            Destination = dest;
            Extension = ext;
            EncodingType = enc;
            ProcessedTime = DateTime.Now;
        }
    }
    */
}
